<?php

use Plugins\AdminBasic\Models\BasicOperationLogs;
use Sc\Util\HtmlElement\El;
use Sc\Util\HtmlStructure\Html\Html;
use Sc\Util\HtmlStructure\Html\Js;

Html::create('操作日志明细');

Html::loadThemeResource('ElementUI');

$des = El::fromCode('<el-descriptions :column="1" :border="true"></el-descriptions>');

/** @var BasicOperationLogs $log */
$log = BasicOperationLogs::find(\App\Util\Helper::request()->query('id'));

Html::js()->vue->set('data', [
    'data' => $log->data,
    'user_info' => $log->user_info,
]);
Html::js()->vue->set('jsonHighlight_data', false);
Html::js()->vue->set('jsonHighlight_user_info', false);

$exception = '无';
if ($log->exception) {
    $trace = preg_replace('/#\d+/', "###$0", $log->exception['trace'],);
    $trace = explode('###', $trace);
    foreach ($trace as &$value) {
        $value = strtr($value, [BASE_PATH => '']);
        if (!str_contains($value, 'vendor')) {
            $value = sprintf("<span style='color: #ec8787'>%s</span>", $value);
        }
    }

    unset($value);

    $messageInfo = explode("\n", $log->exception['message']);
    $messageInfoLength = count($messageInfo);

    $message = $log->exception['message'];
    $position = '';
    $codes = [];

    if ($messageInfoLength > 1) {
        $message = $messageInfo[$messageInfoLength - 2];
        $position = $messageInfo[$messageInfoLength - 1];
        preg_match('/\((\d+)\)/', $position, $match);
        $line = $match[1];
        $codes = array_slice($messageInfo, 1, -2);
        $codes = array_map(function ($v) use ($line){
            $v = strtr($v, [' ' => '&nbsp;&nbsp;']);
            return preg_replace_callback("/^(\d+)\.(.+)/", function ($match) use ($line){
                $v = h('el-text', $match[1] . '.')->setStyle('{color: #ec8787;user-select: none}');
                if ($match[1] == $line) {
                    $v = h('el-text')->setStyle('{color: #ec8787}')->append($v, $match[2]);
                }else{
                    $v = h([$v, $match[2]]);
                }
                return $v;
            }, $v);
        }, $codes);
    }

    $exception = h([
        h('div', implode("<br/>", $codes))->setAttr('v-if', $messageInfoLength > 1)->setStyle("{background: #f5f5f5;padding: 5px}"),
        h('div', h('b', $message)->setStyle("{margin-right: 10px}"))->append(strtr($position, [BASE_PATH => ''])),
        h('div', implode('<br/>', $trace))
    ]);
}

Html::css()->addCss(<<<CSS
li:hover{
    background: #c3c9f1;    
}
CSS
);
$sql = El::double('dl')
    ->append(
        ...array_map(function ($sql){
            return El::double('li')
                ->setAttr('@dblclick', 'selectText')
                ->append($sql);
        }, $log->sql ?: [])
    );
Html::js()->vue->addMethod('selectText', ['event'], Js::code(
    Js::code('const element = event.target;'),
    Js::code('const range = document.createRange();'),
    Js::code('range.selectNodeContents(element);'),
    Js::code('const selection = window.getSelection();'),
    Js::code('selection.removeAllRanges();'),
    Js::code('selection.addRange(range);'),
));

Html::css()->addCss(<<<CSS
    .label-width{
        width: 60px;
        text-align: right!important;
    }
    .el-descriptions__body .el-descriptions__table{
        table-layout: fixed;
    }
    td {
        word-break: break-all;
    }
    .json-highlight {
        background-color: #f5f5f5;
        padding: 10px;
        border-radius: 5px;
        font-family: Consolas, Monaco, monospace;
        font-size: 14px;
        white-space: pre-wrap;
    }
    .json-key {
        color: #c2185b;
    }
    .json-boolean {
        color: #0288d1;
    }
    .json-number {
        color: #f57c00;
    }
    .json-string {
        color: #388e3c;
    }
    div[name=target] {
        white-space: pre-wrap;
        word-wrap: break-word;
    }
CSS);

$item = function ($label, $content) {
    return El::double('el-descriptions-item')
        ->setAttr('label-class-name', 'label-width')
        ->setAttr('label', $label)
        ->text($content);
};


$des->append(
    $item("模块", $log->module . "（请求ID：{$log->request_id}）"),
    $item("地址", "<b style='color: #00BCD4'>{$log->method}</b> {$log->url}"),
    $item("描述", $log->des),
    $item("Query数据", $log->query),
    $item("请求数据",
        El::fictitious()->append(
            El::div()->setAttr('v-if', '!jsonHighlight_data')
                ->append(json_encode($log->data, JSON_UNESCAPED_UNICODE))
                ->append(
                    El::double('el-link')->append('美化')
                        ->setAttr('type', 'primary')
                        ->setAttr('@click', 'jsonHighlight_data = true')
                )
            ,
            El::div()->setAttr('v-else')->setAttr('v-html', 'jsonSyntaxHighlight(data.data)')->setAttr('name', 'target')
        )
    ),
    $item("SQL", $sql),
    $item("异常信息", $exception),
    $item("用户模型", ($log->user_model ?: '') . ($log->user_id ? "（ID：{$log->user_id}）" : "")),
    $item("用户信息",
        El::fictitious()->append(
            El::div()->setAttr('v-if', '!jsonHighlight_user_info')
                ->append('{{ data.user_info }}')
                ->append(
                    El::double('el-link')->append('美化')
                        ->setAttr('type', 'primary')
                        ->setAttr('@click', 'jsonHighlight_user_info = true')
                )
            ,
            El::div()->setAttr('v-else')->setAttr('v-html', 'jsonSyntaxHighlight(data.user_info)')->setAttr('name', 'target')
        )),
    $item("IP", $log->ip),
    $item("时间", $log->create_time),
);

Html::js()->vue->addMethod('jsonSyntaxHighlight', ['json'], Js::code(<<<'JS'
        if (typeof json !== 'string') {
            json = JSON.stringify(json, null, 8);
        }

        // 处理特殊字符
        json = json
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');

        // 使用更精确的正则表达式进行语法高亮
        return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?)/g, function(match) {
            // 匹配键名（带冒号的字符串）
            if (/^"/.test(match) && /:$/.test(match)) {
                return '<span class="json-key">' + match + '</span>';
            }
            // 匹配字符串值
            else if (/^"/.test(match)) {
                return '<span class="json-string">' + match + '</span>';
            }
            // 匹配布尔值或null
            else if (/true|false|null/.test(match)) {
                return '<span class="json-boolean">' + match + '</span>';
            }
            // 匹配数字
            else {
                return '<span class="json-number">' + match + '</span>';
            }
        });
JS));

return $des;